package com.springboot.frame.starter.applet;

import com.springboot.frame.starter.WxCacheTemplate;
import com.springboot.frame.starter.applet.body.resp.AccessTokenRespBody;
import com.springboot.frame.starter.applet.body.resp.Code2SessionRespBody;
import com.springboot.frame.starter.applet.body.resq.Code2SessionResqBody;
import com.springboot.frame.starter.config.WxConfig;
import com.springboot.frame.starter.tools.WxJsonUtils;
import com.springboot.frame.starter.tools.WxException;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.text.MessageFormat;

/**
 * @author liheng
 * @ClassName WxAppletTools
 * @Description
 * @date 2020-12-04 13:55
 */
public class WxAppletTools {
    private RestTemplate wxRestTemplate;
    private WxConfig wxConfig;
    private WxCacheTemplate<String> wxCacheTemplate;
    private final static String ACCESSTOKEN_CACHE_KEY = "accessToken";
    /**
     * 请求参数
     * 属性	类型	默认值	必填	说明
     * appid	string		是	小程序 appId
     * secret	string		是	小程序 appSecret
     * js_code	string		是	登录时获取的 code
     * grant_type	string		是	授权类型，此处只需填写 authorization_cod
     * <p>
     * 返回值：
     * <p>
     * 属性	类型	说明
     * openid	string	用户唯一标识
     * session_key	string	会话密钥
     * unionid	string	用户在开放平台的唯一标识符，若当前小程序已绑定到微信开放平台帐号下会返回，详见 UnionID 机制说明。
     * errcode	number	错误码
     * errmsg	string	错误信息
     */
    private static final String JSCODE_2_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";


    /**
     * 请求参数
     * 属性	类型	默认值	必填	说明
     * grant_type	string		是	填写 client_credential
     * appid	string		是	小程序唯一凭证，即 AppID，可在「微信公众平台 - 设置 - 开发设置」页中获得。（需要已经成为开发者，且帐号没有异常状态）
     * secret	string		是	小程序唯一凭证密钥，即 AppSecret，获取方式同 appid
     * 返回值
     * Object
     * 返回的 JSON 数据包
     * <p>
     * 属性	类型	说明
     * access_token	string	获取到的凭证
     * expires_in	number	凭证有效时间，单位：秒。目前是7200秒之内的值。
     * errcode	number	错误码
     * errmsg	string	错误信息
     */
    private static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";

    public WxAppletTools(RestTemplate wxRestTemplate, WxConfig wxConfig, WxCacheTemplate wxCacheTemplate) {
        this.wxRestTemplate = wxRestTemplate;
        this.wxCacheTemplate = wxCacheTemplate;
        this.wxConfig = wxConfig;
    }


    /**
     * @param resqBody
     * @return
     */
    public Code2SessionRespBody getOpenIdByJscode2session(Code2SessionResqBody resqBody) {
        String requestUrl = MessageFormat.format(JSCODE_2_SESSION_URL, wxConfig.getAppId(), wxConfig.getSecret(), resqBody.getJsCode());
        String respBody = wxRestTemplate.getForEntity(requestUrl, String.class).getBody();
        Code2SessionRespBody code2SessionRespBody = WxJsonUtils.parseObject(respBody, Code2SessionRespBody.class);
        // 判断有误异常
        if (StringUtils.hasLength(code2SessionRespBody.getErrorMsg())) {
            // 抛出错误
            throw new WxException(code2SessionRespBody.getErrorCode() + ":" + code2SessionRespBody.getErrorMsg());
        }
        return code2SessionRespBody;
    }

    /**
     * @param wxConfig
     * @return
     */
    public String getAccessToken(WxConfig wxConfig) {
        String accessToken = wxCacheTemplate.getKey(ACCESSTOKEN_CACHE_KEY);
        if (StringUtils.hasLength(accessToken)) {
            return accessToken;
        }
        String requestUrl = MessageFormat.format(ACCESS_TOKEN_URL, wxConfig.getAppId(), wxConfig.getSecret());
        String respBody = wxRestTemplate.getForEntity(requestUrl, String.class).getBody();
        AccessTokenRespBody accessTokenRespBody = WxJsonUtils.parseObject(respBody, AccessTokenRespBody.class);
        // 判断有误异常
        if (StringUtils.hasLength(accessTokenRespBody.getErrorMsg())) {
            // 抛出错误
            throw new WxException(accessTokenRespBody.getErrorCode() + ":" + accessTokenRespBody.getErrorMsg());
        }
        return accessTokenRespBody.getAccessToken();
    }
}
